﻿/*!
 * @file drv_lpspi_edma.h
 * @author suyong_yq@126.com
 * @note
 * 本模块实现通过EDMA驱动LPSPI传输引擎收发数据
 */

#ifndef __DRV_LPSPI_EDMA_H__
#define __DRV_LPSPI_EDMA_H__

#include "hal_common.h"
#include "hal_lpspi.h"
#include "hal_dmamux.h"
#include "hal_edma.h"

/*!
 * @brief 包含的硬件资源
 * @note 对于各个模块的配置将在应用中固化
 */
typedef struct
{
    LPSPI_Type *LpspiBase;     /* SPI Base. */

    /* DMA SPI Tx channel. */
    uint32_t   EdmaLpspiTxChnIdx;
    DMAMUX_TriggerSource_T EdmaLpspiTxTriggerSource;

    /* DMA SPI Rx channel. */
    uint32_t   EdmaLpspiRxChnIdx;
    DMAMUX_TriggerSource_T EdmaLpspiRxTriggerSource;
    IRQn_Type  EdmaRxChnIRQn; /* Edma Rx通道的传输完成中断向量号 */

} LPSPI_EDMA_HwDev_T;

/*!
 * @brief 操作句柄
 * @note  保存全局变量，传输状态等等
 */
typedef struct
{
    LPSPI_EDMA_HwDev_T *HwDevPtr; /* 关联硬件资源 */

    uint8_t TxDummyData; /* 在发送无效时，Tx DMA通道临时使用的源地址 */
    uint8_t RxDummyData; /* 在接收无效时，Rx DMA通道临时使用的目的地址 */

    void (*xferDoneCallbackFunc)(void); /* 传输完成的回调函数，每次传输都可重新设定 */
} LPSPI_EDMA_MasterXferHandler_T;

/*!
 * @brief 初始化传输操作
 * @note  初始化硬件，关联结构体数据
 */
void LPSPI_EDMA_MasterInit(
    LPSPI_EDMA_MasterXferHandler_T *xferHandler,
    LPSPI_EDMA_HwDev_T       *hwDevPtr,
    LPSPI_MasterConfig_T     *lpspiConfigPtr
);

/*!
 * @brief 启动基于DMA自动搬运数据的SPI传输
 * @note
 * 本函数配置EDMA及LPSPI处于工作状态，并触发两个EDMA通道开始搬运LPSPI的数据。
 * 传输完成的回调函数是可选的，但传输完成之后一定会有驱动模块中定义的收尾函数被
 * 调用，因此为了配合本函数的完成，应用程序还需要定义一个接收中断服务的函数，然
 * 后在其中调用驱动模块定义的处理函数。
 * @param xferHandler 保存状态信息的结构体指针。
 * @param txBufPtr    发送序列存储区的指针。在仅为接收模式下，可为NULL。
 * @param rxBufPtr    获取序列存储区的指针。在仅为发送模式下，可为NULL。
 * @param xferLen     传输序列的长度。以字节为单位，传输单元也为字节。
 * @param xferDonecallback 传输完成回调函数。在master模式下，传输结束事件绑定到DMA
 *                    在SPI的接收通道上，当接收完成后，在应用程序定义的中断服务
 *                    函数中调用驱动模块预先设计好的服务程序，其中就包含了对回调
 *                    函数的调用。
 */
void LPSPI_EDMA_StartMasterXfer(
    LPSPI_EDMA_MasterXferHandler_T *xferHandler,
    uint8_t *txBufPtr, uint8_t *rxBufPtr, uint32_t xferLen,
    void (*xferDonecallback)(void)
);

/*!
 * @brief 驱动模块中定义的Master传输完成服务程序
 * @note
 * 本函数需要在应用程序中被Rx DMA通道的中断服务函数中调用
 */
void LPSPI_EDMA_MasterXferIRQHandler(LPSPI_EDMA_MasterXferHandler_T *xferHandler);

#endif /* __DRV_LPSPI_EDMA_H__ */
